package notesDetection.SFT;

import java.util.Set;
import notesDetection.Utilities.GeneralNoteDetection;

public class ArraySFTFunction implements SFTFunction{

	private Complex[] values;
	private double infNorm; //Uninitialized
	

	/**if user somehow knows infNorm, he will kindly tell us.
	 * default should be 1.0, for WAV files values are bounded by -1 & 1. */
	public ArraySFTFunction(Complex[] values, double infNorm){
		this.values=values;
		this.infNorm=infNorm;
	}
	//the same, for users who don't like complexes...
	public ArraySFTFunction(double[] values, double infNorm){
		this.values= new Complex[values.length];
		for(int i=0;i<values.length;i++){
			this.values[i] = new Complex(values[i],0);
		}
		this.infNorm=infNorm;
	}
	
	public Complex funcValue(int x) {
		return values[x];
	}

	@Override
	public double calcTwoNorm() {
		Set<Integer> random_set = SFTUtils.RandomSet(10, values.length);
		double twoNormSqr=0;
		for(Integer a : random_set){
			twoNormSqr += funcValue(a).sqrdNorm();
		}
		twoNormSqr = twoNormSqr/random_set.size(); //average

		return Math.sqrt(twoNormSqr);
	}

	@Override
	public double calcInfNorm() {
		return infNorm;
	}

	@Override
	public int getN() {
		return values.length;
	}
	public Complex SampleCoeffValue(int coeff, int cycleLength) {
		
		final int SAMPLE_COUNT = 800;
		//	Use 100 samples
		double realSum = 0;
		double imagSum = 0;
		
		//	An = Expectation{x[n]e^(-j*2pi*n/N)}
		for(int iteration = 0; iteration < SAMPLE_COUNT; iteration++)
		{
			int n = GeneralNoteDetection.GetRandomInt(0, getN() - 1);
			double sineValue = Math.sin(2 * Math.PI * n * coeff / cycleLength);
			double cosineValue = Math.cos(2 * Math.PI * n * coeff / cycleLength);
			
			realSum += funcValue(n).Re() * cosineValue - funcValue(n).Im() * sineValue;
			imagSum += funcValue(n).Im() * cosineValue + funcValue(n).Re() * sineValue;
			
		}
		//	Multiply by 2 to compensate for negative coefficient (required for all coeffs but 0!)
		//	We never sample the DC (0) coefficient, so we may ignore that...
		return new Complex(2 * realSum / SAMPLE_COUNT, 2 * imagSum / SAMPLE_COUNT);
	}

}
